home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Alles Voor Internet / Tout Pour Internet
/
alles voor internet.iso
/
MacInternet™
/
Telnet
/
NCSA
/
tn3270 2.4d7 source
/
SPPC
/
driver.c
next >
Wrap
Text File
|
1991-05-28
|
11KB
|
505 lines
#if !defined(USEDUMP)
#include "drvlib.h"
#else
#pragma load "drvDumpFile"
#endif
#include "sppcinterface.h"
#define MSGNUM 24 /* number of outstanding messages allowed */
#define CLIENTNUM 8 /* number of simultaneous clients */
#define NAMELENGTH 32 /* significant chars. in client name */
#define MSGLENGTH 128 /* maximum length of message */
typedef struct {
unsigned char name[NAMELENGTH+1];
unsigned char inuse;
short refnum;
} clientrec;
typedef struct {
unsigned char data[MSGLENGTH];
unsigned long id;
unsigned long replyid;
short datalen;
short torefnum;
short fromrefnum;
unsigned char inuse;
} msgrec;
struct drvGlobals {
short refcounter; /* last refnum given out */
unsigned long msgcounter; /* last msg id given out */
clientrec clist[CLIENTNUM]; /* client data */
msgrec mlist[MSGNUM]; /* message data */
};
/* subroutine prototypes */
OSErr doregister(struct drvGlobals**, unsigned char*, short*);
OSErr doderegister(struct drvGlobals**, short);
OSErr dolookup(struct drvGlobals**, unsigned char*, short*);
OSErr dosend(struct drvGlobals**, short, unsigned long,
short, Handle, unsigned short, unsigned long*);
OSErr doget(struct drvGlobals**, short, unsigned long, short *,
Handle, unsigned short*, unsigned long*, unsigned long *);
OSErr doclear(struct drvGlobals**, short);
OSErr dodelmsg(struct drvGlobals**, unsigned long*);
short lookupname(clientrec*, unsigned char *);
short lookupref(clientrec*, short);
void msgclear(msgrec*, short);
pascal OSErr DRVROpen(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB)
THz hz;
if (dCtl->dCtlStorage != 0) { /* return if already open */
return(noErr);
}
hz = GetZone(); /* allocate storage for globals */
SetZone(SystemZone());
dCtl->dCtlStorage = NewHandle((Size)sizeof(struct drvGlobals));
SetZone(hz);
if (dCtl->dCtlStorage == 0) {
return(mFulErr);
}
else { /* clear storage and return */
memset(*(dCtl->dCtlStorage), 0, sizeof(struct drvGlobals));
return(noErr);
}
}
pascal OSErr DRVRClose(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB)
if (dCtl->dCtlStorage == 0) { /* return if not open */
return(notOpenErr);
}
/* dispose of global storage */
DisposHandle(dCtl->dCtlStorage);
return(noErr);
}
pascal OSErr DRVRControl(CntrlParam *ctlPB, DCtlPtr dCtl)
{
parmrec * pmr;
struct drvGlobals** ghandle;
OSErr rc;
/* get parameter structure pointer from csParam array */
memcpy(&pmr, ctlPB->csParam, 4);
ghandle = (struct drvGlobals**)(dCtl->dCtlStorage);
if (ghandle == 0) {
return(notOpenErr);
}
HLock((Handle)ghandle);
switch(ctlPB->csCode) {
case SPPCreg:
rc = doregister(ghandle, pmr->name, pmr->refptr);
break;
case SPPCdereg:
rc = doderegister(ghandle, pmr->refnum);
break;
case SPPClookup:
rc = dolookup(ghandle, pmr->name, pmr->refptr);
break;
case SPPCsend:
rc = dosend(ghandle, pmr->refnum, pmr->replyid,
pmr->refnum2, pmr->msg, pmr->msglen,
pmr->msgid);
break;
case SPPCget:
rc = doget(ghandle, pmr->refnum, pmr->replyid,
pmr->refptr, pmr->msg, pmr->msglenptr,
pmr->msgid, pmr->replyidptr);
break;
case SPPCclear:
rc = doclear(ghandle, pmr->refnum);
break;
case SPPCdelmsg:
rc = dodelmsg(ghandle, pmr->msgid);
break;
default:
rc = paramErr;
break;
}
HUnlock((Handle)ghandle);
return(rc);
}
/* The following calls are not implemented by this driver */
pascal OSErr DRVRPrime(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB, dCtl)
return(unimpErr);
}
pascal OSErr DRVRStatus(CntrlParam *ctlPB, DCtlPtr dCtl)
{
#pragma unused (ctlPB, dCtl);
return(unimpErr);
}
/* subroutines for control functions */
OSErr doregister(struct drvGlobals** gh, unsigned char* cName,
short* cRefNum)
{
unsigned char newname[NAMELENGTH+1];
short i, slen, match;
clientrec * cp;
(*cRefNum) = 0;
slen = strlen(cName);
if (slen == 0) {
return(bdNamErr);
}
if (slen > NAMELENGTH) slen = NAMELENGTH;
memset(newname, 0, NAMELENGTH+1);
memcpy(newname, cName, slen);
cp = (*gh)->clist; /* pointer to client array */
/* check if name is in use */
match = lookupname(cp, newname);
/* if name is in use, return refnum and error code */
if (match >= 0) {
(*cRefNum) = cp[match].refnum;
return(dupFNErr);
}
/* find an empty slot for new name */
match = -1;
for (i=0; i < CLIENTNUM; i++) {
if (cp[i].inuse == 0) {
match = i;
break;
}
}
/* check for no more room */
if (match == -1) {
return(dirFulErr);
}
/* define new client */
memcpy(cp[match].name, newname, NAMELENGTH+1);
cp[match].inuse = 1;
(*gh)->refcounter++;
cp[match].refnum = (*gh)->refcounter;
(*cRefNum) = cp[match].refnum;
return(noErr);
}
OSErr doderegister(struct drvGlobals** gh, short cRefNum)
{
short match;
clientrec * cp;
msgrec * mp;
cp = (*gh)->clist; /* pointer to client array */
/* check if refnum is in use */
match = lookupref(cp, cRefNum);
/* error if refnum not found */
if (match == -1) {
return(rfNumErr);
}
/* delete this client */
memset(cp[match].name, 0, NAMELENGTH+1);
cp[match].inuse = 0;
cp[match].refnum = 0;
/* also delete any pending messages */
mp = (*gh)->mlist; /* pointer to message array */
msgclear(mp, cRefNum);
return(noErr);
}
OSErr dolookup(struct drvGlobals** gh, unsigned char* cName,
short* cRefNum)
{
unsigned char lkpname[NAMELENGTH+1];
short slen, match;
clientrec * cp;
(*cRefNum) = 0;
slen = strlen(cName);
if (slen == 0) {
return(bdNamErr);
}
if (slen > NAMELENGTH) slen = NAMELENGTH;
memset(lkpname, 0, NAMELENGTH+1);
memcpy(lkpname, cName, slen);
cp = (*gh)->clist; /* pointer to client array */
/* check if name is in use */
match = lookupname(cp, lkpname);
/* if name is in use, return refnum and success code */
if (match >= 0) {
(*cRefNum) = cp[match].refnum;
return(noErr);
}
/* return not found error */
return(fnfErr);
}
OSErr dosend(struct drvGlobals** gh, short cRefNum,
unsigned long replyId, short toRefNum,
Handle theMessage, unsigned short msglen,
unsigned long *msgid)
{
short i, match;
clientrec * cp;
msgrec * mp;
Size hsize;
(*msgid) = 0; /* initialize result */
cp = (*gh)->clist; /* pointer to client array */
/* check if source refnum is valid */
match = lookupref(cp, cRefNum);
/* error if source refnum not found */
if (match == -1) {
return(rfNumErr);
}
/* check if destination refnum is valid */
match = lookupref(cp, toRefNum);
/* error if destination refnum not found */
if (match == -1) {
return(rfNumErr);
}
/* check message length is valid */
if ((msglen == 0) || (msglen > MSGLENGTH)) {
return(memSCErr);
}
/* check message handle is valid */
hsize = GetHandleSize(theMessage);
if (hsize < msglen) {
return(memSCErr);
}
mp = (*gh)->mlist; /* pointer to message array */
/* find an empty slot for new message */
match = -1;
for (i=0; i < MSGNUM; i++) {
if (mp[i].inuse == 0) {
match = i;
break;
}
}
/* check for no more room */
if (match == -1) {
return(dirFulErr);
}
/* define new message */
memcpy(mp[match].data, (*theMessage), (size_t)msglen);
mp[match].datalen = msglen;
mp[match].torefnum = toRefNum;
mp[match].replyid = replyId;
mp[match].fromrefnum = cRefNum;
mp[match].inuse = 1;
(*gh)->msgcounter++;
mp[match].id = (*gh)->msgcounter;
(*msgid) = mp[match].id;
return(noErr);
}
OSErr doget(struct drvGlobals** gh, short cRefNum,
unsigned long replyId, short* fromRefNum,
Handle theMessage, unsigned short *msglenptr,
unsigned long * msgid, unsigned long * replyidptr)
{
short i, match;
clientrec * cp;
msgrec * mp;
Size hsize;
cp = (*gh)->clist; /* pointer to client array */
(*fromRefNum) = 0; /* initialize results */
(*msglenptr) = 0;
(*msgid) = 0;
/* check if destination refnum is valid */
match = lookupref(cp, cRefNum);
/* error if destination refnum not found */
if (match == -1) {
return(rfNumErr);
}
mp = (*gh)->mlist; /* pointer to message array */
/* search for a message for the destination */
/* return the matching message with the lowest message id */
match = -1;
for (i=0; i < MSGNUM; i++) {
if (mp[i].inuse && (mp[i].torefnum == cRefNum) &&
((mp[i].replyid == replyId) || (replyId == 0))) {
if (match == -1) {
match = i;
}
else {
if (mp[i].id < mp[match].id) {
match = i;
}
}
}
}
/* check for no message found */
if (match == -1) {
return(fnfErr);
}
/* return message control data */
(*msglenptr) = mp[match].datalen;
(*fromRefNum) = mp[match].fromrefnum;
(*msgid) = mp[match].id;
(*replyidptr) = mp[match].replyid;
/* check message handle is valid */
hsize = GetHandleSize(theMessage);
if (hsize < mp[match].datalen) {
return(memSCErr);
}
/* return the message data */
memcpy(*theMessage, mp[match].data, mp[match].datalen);
/* delete this message */
memset(mp[match].data, 0, MSGLENGTH);
mp[match].datalen = mp[match].torefnum = mp[match].fromrefnum = 0;
mp[match].replyid = 0;
mp[match].inuse = 0;
mp[match].id = 0;
return(noErr);
}
OSErr doclear(struct drvGlobals** gh, short cRefNum)
{
short match;
clientrec * cp;
msgrec * mp;
cp = (*gh)->clist; /* pointer to client array */
/* check if refnum is in use */
match = lookupref(cp, cRefNum);
/* error if refnum not found */
if (match == -1) {
return(rfNumErr);
}
/* delete any pending messages */
mp = (*gh)->mlist; /* pointer to message array */
msgclear(mp, cRefNum);
return(noErr);
}
OSErr dodelmsg(struct drvGlobals** gh, unsigned long *msgid)
{
short i, match;
msgrec * mp;
mp = (*gh)->mlist; /* pointer to message array */
/* look for a matching message */
match = -1;
for (i=0; i < MSGNUM; i++) {
if (mp[i].id == (*msgid)) {
match = i;
break;
}
}
/* check for message not found */
if (match == -1) {
return(fnfErr);
}
/* delete this message */
memset(mp[match].data, 0, MSGLENGTH);
mp[match].datalen = mp[match].torefnum = mp[match].fromrefnum = 0;
mp[match].replyid = 0;
mp[match].inuse = 0;
mp[match].id = 0;
return(noErr);
}
short lookupname(clientrec *cp, unsigned char *name)
{
short i, match;
/* Return clist index for name, or -1 */
match = -1;
for (i=0; i < CLIENTNUM; i++) {
if (cp[i].inuse) {
if (strcmp(name, cp[i].name) == 0) {
match = i;
break;
}
}
}
return(match);
}
short lookupref(clientrec *cp, short refnum)
{
short i, match;
/* Return clist index for refnum, or -1 */
match = -1;
for (i=0; i < CLIENTNUM; i++) {
if (cp[i].inuse) {
if (cp[i].refnum == refnum) {
match = i;
break;
}
}
}
return(match);
}
void msgclear(msgrec* mp, short toref)
{
short i;
/* delete any messages with a matching torefnum */
for (i=0; i < MSGNUM; i++) {
if (mp[i].torefnum == toref) {
memset(mp[i].data, 0, MSGLENGTH);
mp[i].datalen = mp[i].torefnum = mp[i].fromrefnum = 0;
mp[i].replyid = 0;
mp[i].inuse = 0;
mp[i].id = 0;
}
}
}